/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_GRAPHIC_H
#define M_GRAPHIC_H

#include "timer.h"
#include "signal.h"
#include "log.h"
#include "singleton.h"
#include "rendersystem.h"
#include "scenemanager.h"
#include "movableobject.h"
#include "physicsystem.h"

namespace Engine
{
	/**
	*   Root object handles main graphic engine systems(Facade).
	*/
	class Graphic: public Singleton<Graphic>
	{
	public:
		typedef std::map<std::string, RefPtr<RenderSystemFactory,WeakPtrExtension> >  RenderSystemFactoriesMap;
		typedef std::map<std::string, RefPtr<SceneManagerFactory,WeakPtrExtension> >  SceneManagerFactoriesMap;
		typedef std::map<std::string, RefPtr<SceneManager,WeakPtrExtension> >         SceneManagerMap;
		typedef std::map<std::string, RefPtr<MovableObjectFactory,WeakPtrExtension> > MovableObjectFactoriesMap;
		typedef std::map<std::string, RefPtr<PhysicSystemFactory,WeakPtrExtension> >  PhysicSystemFactoriesMap;
		typedef std::map<std::string, RefPtr<PhysicSystem,WeakPtrExtension> >		  PhysicSystemMap;

		/**
		*   Initialize all systems;
		*/
		Graphic();

		/**
		*   Stop all systems;
		*/
		~Graphic();

		/**
		*   Set main render system for engine.
		*/
		RenderSystemPtr CreateRenderSystem(const std::string& type);

		/**
		*   Return current render system.
		*/
		RenderSystemPtr GetRenderSystem(){return m_renderSystem;}

		/**
		*   Render one frame.
		*/
		void RenderOneFrame();

		/**
		*   Fired when frame rendering started.
		*   Parameter is time since last frame.
		*/
		Signal<unsigned long> FrameStartSignal;

		/**
		*   Fired when frame rendering finished.
		*   Parameter is time since frame start.
		*/
		Signal<unsigned long> FrameEndSignal;

		/**
		*   Create new scene manager of specified type and name.
		*/
		SceneManagerPtr CreateSceneManager(const std::string& type, const std::string& name);

		/**
		*   Create new physic system of specified type and name.
		*/
		PhysicSystemPtr CreatePhysicSystem(const std::string& type, const std::string& name);

		/**
		*   Return pointer to factory for creating objects of specified type, or null if type not supported.
		*/
		MovableObjectFactoryPtr GetMovableObjectFactory(const std::string& type);

	private:

		/**
		*   System specific function to process windows events.
		*/
		void ProcessMessages();

		/**
		*   Render frame in all render targets.
		*/
        void UpdateAllRenderTargets();

	private:

		RefPtr<RenderSystem, WeakPtrExtension> m_renderSystem;

		Timer m_timer;
		unsigned long m_frameEndTime;

		RenderSystemFactoriesMap m_renderSystemFactories;

		SceneManagerFactoriesMap m_sceneManagerFactories;
		SceneManagerMap m_sceneManagers;

		MovableObjectFactoriesMap m_movableObjectFactories;

		PhysicSystemFactoriesMap m_physicSystemFactories;
		PhysicSystemMap          m_physicSystems;
	};
}

#endif
